// sim_db_fpga_tb.v

`timescale 10 ns/1 ns
module sim_db_fpga_tb;

parameter FPGA_Ver_ADDR= 12'h800;                        //                                    
parameter DATA_AAAA_ADDR=12'h802;                        //
parameter DATA_5555_ADDR=12'h804;                        //
parameter DATA_FFFF_ADDR=12'h806;                        //
parameter DATA_0000_ADDR=12'h808;                        //

parameter FPGA_SPD_MODE_ADDR=12'h810;                    // 输出模式寄存器，低6位为输出模式选择 
parameter FPGA_OUTPUT_CONTROL_ADDR=12'h812;              // 0-5 SPD1-spd12  6  dop   1 - enable; 0 - disable
parameter FPGA_SPD_LOAD_ADDR=12'h814;                    // SPD parameter load

parameter FPGA_SPD1_FCONFIG_LOW_ADDR= 12'h820;           // 1，2通道低16位频率参数
parameter FPGA_SPD1_FCONFIG_HIGH_ADDR=12'h822;           // 1，2通道高16位频率参数
parameter FPGA_SPD2_FCONFIG_LOW_ADDR= 12'h824;           // 3，4通道低16位频率参数
parameter FPGA_SPD2_FCONFIG_HIGH_ADDR=12'h826;           // 3，4通道高16位频率参数
parameter FPGA_SPD3_FCONFIG_LOW_ADDR= 12'h828;           // 5，6通道低16位频率参数
parameter FPGA_SPD3_FCONFIG_HIGH_ADDR=12'h82a;           // 5，6通道高16位频率参数
parameter FPGA_SPD4_FCONFIG_LOW_ADDR= 12'h830;           // 7，8通道低16位频率参数
parameter FPGA_SPD4_FCONFIG_HIGH_ADDR=12'h832;           // 7，8通道高16位频率参数
parameter FPGA_SPD5_FCONFIG_LOW_ADDR= 12'h834;           // 9，10通道低16位频率参数
parameter FPGA_SPD5_FCONFIG_HIGH_ADDR=12'h836;           // 9，10通道高16位频率参数
parameter FPGA_SPD6_FCONFIG_LOW_ADDR= 12'h838;           // 11，12通道低16位频率参数
parameter FPGA_SPD6_FCONFIG_HIGH_ADDR=12'h83a;           // 11，12通道高16位频率参数

parameter FPGA_SPD1_PCONFIG_LOW_ADDR= 12'h840;           // 1，2通道低16相位率参数  最高位判断哪个通道相位在前  1，2通道在先，0，1通道在先
parameter FPGA_SPD1_PCONFIG_HIGH_ADDR=12'h842;           // 1，2通道高16相位率参数  
parameter FPGA_SPD2_PCONFIG_LOW_ADDR= 12'h844;           // 3，4通道低16相位率参数  
parameter FPGA_SPD2_PCONFIG_HIGH_ADDR=12'h846;           // 3，4通道高16相位率参数  
parameter FPGA_SPD3_PCONFIG_LOW_ADDR= 12'h848;           // 5，6通道低16相位率参数  
parameter FPGA_SPD3_PCONFIG_HIGH_ADDR=12'h84a;           // 5，6通道高16相位率参数  
parameter FPGA_SPD4_PCONFIG_LOW_ADDR= 12'h850;           // 7，8通道低16相位率参数  
parameter FPGA_SPD4_PCONFIG_HIGH_ADDR=12'h852;           // 7，8通道高16相位率参数  
parameter FPGA_SPD5_PCONFIG_LOW_ADDR= 12'h854;           // 9，10通道低16位相位参数                                      
parameter FPGA_SPD5_PCONFIG_HIGH_ADDR=12'h856;           // 9，10通道高16位频率参数 
parameter FPGA_SPD6_PCONFIG_LOW_ADDR= 12'h858;           // 11，12通道低16位相位参数
parameter FPGA_SPD6_PCONFIG_HIGH_ADDR=12'h85a;           // 11，12通道高16位相位参数

parameter FPGA_SPD1_PLUSE_ADDR =12'h860;                    // 1，2通道脉冲个数参数
parameter FPGA_SPD2_PLUSE_ADDR =12'h862;                    // 3，4通道脉冲个数参数
parameter FPGA_SPD3_PLUSE_ADDR =12'h864;                    // 5，6通道脉冲个数参数
parameter FPGA_SPD4_PLUSE_ADDR =12'h866;                    // 7，8通道脉冲个数参数
parameter FPGA_SPD5_PLUSE_ADDR =12'h868;                    // 9，10通道脉冲个数参数
parameter FPGA_SPD6_PLUSE_ADDR =12'h86a;                    // 11，12通道脉冲个数参数 

parameter FPGA_LIMITED_PULSE_FINISHED_ADDR=12'h870;         // 低6位为有限个数脉冲输出结束 1 表示输出结束，当重新加载脉冲个数后自动为0

parameter FPGA_CD_TI_OUTPUT_ADDR = 12'h880;                 //  TI  CD2  CD1               
                                                            //  2    1    0   
parameter FPGA_DOP_FCONFIG_LOW_ADDR=  12'h882;              // dop 低16位频率参数
parameter FPGA_DOP_FCONFIG_HIGH_ADDR= 12'h884;              // dop 高16位频率参数

parameter FPGA_IO_OUTPUT_ADDR = 12'h890;                      // IO输出寄存器 
parameter FPGA_IO_LED_ADDR = 12'h8a0;                      // IO输出寄存器

parameter FPGA_SPD1_INIT_LOW_ADDR= 12'h8b0;
parameter FPGA_SPD1_INIT_HIGH_ADDR= 12'h8b2;
parameter FPGA_SPD2_INIT_LOW_ADDR= 12'h8b4;
parameter FPGA_SPD2_INIT_HIGH_ADDR= 12'h8b6;
parameter FPGA_SPD3_INIT_LOW_ADDR= 12'h8b8;
parameter FPGA_SPD3_INIT_HIGH_ADDR= 12'h8ba;

parameter FPGA_SPD4_INIT_LOW_ADDR= 12'h8c0;
parameter FPGA_SPD4_INIT_HIGH_ADDR= 12'h8c2;
parameter FPGA_SPD5_INIT_LOW_ADDR= 12'h8c4;
parameter FPGA_SPD5_INIT_HIGH_ADDR= 12'h8c6;
parameter FPGA_SPD6_INIT_LOW_ADDR= 12'h8c8;
parameter FPGA_SPD6_INIT_HIGH_ADDR= 12'h8ca;

parameter SPD2_LOAD_FREQ_PARAM = 16'b0000_0000_0000_0100;
parameter SPD2_LOAD_INIT_PARAM = 16'b0000_0000_0000_1000;

// wr reg
`define WR_REG(addr, data) begin #(3*clk_period) la = addr; \
	#(2*clk_period) ld_in = data; \
	#(5*clk_period) lwr_n = 1'b0; \
	#(40*clk_period) lwr_n = 1'b1; \
	end
	
	// rd reg
`define RD_REG(addr) begin #(3*clk_period) la = addr; \
	#(5*clk_period) lrd_n = 1'b0; \
	#(40*clk_period) lrd_n = 1'b1; \
	end

reg clk;
reg rst_n;
reg  [11:0] la;
reg  [15:0] ld_in;
reg lrd_n;
reg lwr_n;
reg lcs_n;
reg lclk;
reg  [15:0]  pluse_number;
reg limited_pluse;


wire [15:0] ld_out;
wire la_dir;
wire la_oe_n;
wire ld_dir;
wire ld_oe_n;
wire [5:0] spd1_ch;
wire [5:0] spd2_ch;
wire dop_pwm;
wire out1;
wire out2;
wire led1;
wire led2;
wire btm_cd1;
wire btm_cd2;
wire ti_lock;
wire ti_led;
wire sig_latch;
wire sig_clr;
wire cspd1_latch;
wire cspd1_clr;
wire cspd2_latch;
wire cspd2_clr;
wire mvb_lcs_n;
wire mvb_rst_n;

reg spi_sdo;
wire spi_clk;
wire spi_sdi;

parameter clk_period = 4; // clk period 25MHz = 40ns

parameter wr_period = 10000;

parameter DELY_PERIO = 20000;


// instance
sim_db top_inst(
	.I_rst_n(rst_n), 
	.clock(clk),
	.I_la(la),
	.IO_ld_in(ld_in),
	.IO_ld_out(ld_out),
	.I_lrd_n(lrd_n),
	.I_lwr_n(lwr_n),
	.I_lcs_n(lcs_n),
	.I_lclk(lclk),
	.O_la_dir(la_dir),
	.O_la_oe_n(la_oe_n),
	.O_ld_dir(ld_dir),
	.O_ld_oe_n(ld_oe_n),
	.O_spd1_ch(spd1_ch),
	.O_spd2_ch(spd2_ch),
	.O_dop_pwm(dop_pwm),
	.O_out1(out1),
	.O_out2(out2),
	.O_led1(led1),
	.O_led2(led2),
	.O_btm_cd1(btm_cd1),
	.O_btm_cd2(btm_cd2),
	.O_ti_lock(ti_lock),
	.O_ti_led(ti_led),
	.O_sig_latch(sig_latch),
	.O_sig_clr(sig_clr),
	.O_cspd1_latch(cspd1_latch),
	.O_cspd1_clr(cspd1_clr),
	.O_cspd2_latch(cspd2_latch),
	.O_cspd2_clr(cspd2_clr),
	.O_mvb_lcs_n(mvb_lcs_n),
	.O_mvb_rst_n(mvb_rst_n),
	.Spi_sdo(spi_sdo),
	.Spi_clk(spi_clk),
	.Spi_sdi(spi_sdi)
	);

// expected result
//initial begin
	
//end

// clock generator
always #(clk_period/2) clk = ~clk;

initial begin
	clk = 1'b0;
	rst_n = 1'b0; // rst invalid
	la = 12'h000;
	ld_in = 16'h0000;
	lrd_n = 1'b1;
	lwr_n = 1'b1;
	lcs_n = 1'b1;

	#(10) rst_n = 1'b1; // rst valid
	
	#(2) lcs_n = 1'b0; // cs valid
end

initial begin

	#(20) ;
	`WR_REG(FPGA_SPD_LOAD_ADDR, 16'h0000) // load to zero
	`WR_REG(FPGA_SPD_MODE_ADDR, 16'h0000) // mode 0-wuxian 1-youxian
	// `WR_REG(FPGA_SPD1_PLUSE_ADDR, 16'h0000) // pulse
	`WR_REG(FPGA_SPD2_INIT_LOW_ADDR, 16'h0000) // init low
	`WR_REG(FPGA_SPD2_INIT_HIGH_ADDR, 16'h0000) // init high
	
	`WR_REG(FPGA_SPD2_FCONFIG_LOW_ADDR, 16'h0000) // f low
	`WR_REG(FPGA_SPD2_FCONFIG_HIGH_ADDR, 16'h0000) // f high
	`WR_REG(FPGA_SPD2_PCONFIG_LOW_ADDR, 16'h0000) // p low
	`WR_REG(FPGA_SPD2_PCONFIG_HIGH_ADDR, 16'h8000) // p high
	`WR_REG(FPGA_SPD_LOAD_ADDR, (SPD2_LOAD_FREQ_PARAM|SPD2_LOAD_INIT_PARAM)) // load
	`WR_REG(FPGA_OUTPUT_CONTROL_ADDR, 16'h001D) // channel output control
	
	#(DELY_PERIO) ;
	`WR_REG(FPGA_SPD_LOAD_ADDR, 16'h0000) // load to zero
	`WR_REG(FPGA_SPD2_INIT_LOW_ADDR, 16'h0064) // init low
	`WR_REG(FPGA_SPD2_INIT_HIGH_ADDR, 16'h0000) // init high
	
	`WR_REG(FPGA_SPD_LOAD_ADDR, (SPD2_LOAD_INIT_PARAM)) // load
	
	#(DELY_PERIO) ;  // 09c4 is 10KHz
	`WR_REG(FPGA_SPD_LOAD_ADDR, 16'h0000) // load to zero
	
	`WR_REG(FPGA_SPD2_FCONFIG_LOW_ADDR, 16'h09c4) // f low
	`WR_REG(FPGA_SPD2_FCONFIG_HIGH_ADDR, 16'h0000) // f high
	`WR_REG(FPGA_SPD2_PCONFIG_LOW_ADDR, 16'h0271) // p low
	`WR_REG(FPGA_SPD2_PCONFIG_HIGH_ADDR, 16'h8000) // p high
	
	`WR_REG(FPGA_SPD_LOAD_ADDR, (SPD2_LOAD_FREQ_PARAM)) // load

	#(DELY_PERIO*2) ;
	`WR_REG(FPGA_SPD_LOAD_ADDR, 16'h0000) // load to zero
	`WR_REG(FPGA_SPD2_INIT_LOW_ADDR, 16'h0000) // init low
	`WR_REG(FPGA_SPD2_INIT_HIGH_ADDR, 16'h0000) // init high
	
	`WR_REG(FPGA_SPD_LOAD_ADDR, (SPD2_LOAD_INIT_PARAM)) // load
	
	#(DELY_PERIO*3) ;  // 4e2 is 20KHz
	`WR_REG(FPGA_SPD_LOAD_ADDR, 16'h0000) // load to zero
	
	`WR_REG(FPGA_SPD2_FCONFIG_LOW_ADDR, 16'h04e2) // f low
	`WR_REG(FPGA_SPD2_FCONFIG_HIGH_ADDR, 16'h0000) // f high
	`WR_REG(FPGA_SPD2_PCONFIG_LOW_ADDR, 16'h0138) // p low
	`WR_REG(FPGA_SPD2_PCONFIG_HIGH_ADDR, 16'h0000) // p high
	
	`WR_REG(FPGA_SPD_LOAD_ADDR, (SPD2_LOAD_FREQ_PARAM)) // load
	
	#(DELY_PERIO*2) ; // 186A0 is 10K
	`WR_REG(FPGA_SPD_LOAD_ADDR, 16'h0000) // load to zero
	`WR_REG(FPGA_SPD2_INIT_LOW_ADDR, 16'h86A0) // init low
	`WR_REG(FPGA_SPD2_INIT_HIGH_ADDR, 16'h0001) // init high
	
	`WR_REG(FPGA_SPD_LOAD_ADDR, (SPD2_LOAD_INIT_PARAM)) // load

	#(DELY_PERIO) ;  // 3D090 is 1KHz 16E36 is 135du of 1KHz
	`WR_REG(FPGA_SPD_LOAD_ADDR, 16'h0000) // load to zero
	
	`WR_REG(FPGA_SPD2_FCONFIG_LOW_ADDR, 16'hD090) // f low
	`WR_REG(FPGA_SPD2_FCONFIG_HIGH_ADDR, 16'h0003) // f high
	`WR_REG(FPGA_SPD2_PCONFIG_LOW_ADDR, 16'h6E36) // p low
	`WR_REG(FPGA_SPD2_PCONFIG_HIGH_ADDR, 16'h0001) // p high
	
	`WR_REG(FPGA_SPD_LOAD_ADDR, (SPD2_LOAD_FREQ_PARAM)) // load
	/*
	#(DELY_PERIO*200) ;
	#(20)
	`RD_REG(FPGA_Ver_ADDR) // version
	`RD_REG(DATA_AAAA_ADDR) // data aaaa
	*/
	

	#(4*wr_period) ;
	$stop;
end


/*
// compare result
always@(posedge PHR) begin
	if (tbErr != tbExpResult) begin
		$display("Time %d ns, error!", $time);
	end
	else begin
		//$display("ok!");
	end
end
*/

endmodule
